---
title: Theming
---

import ColorKeys from '../components/color-keys'

# Theming

Theming with Theme UI is based on a [Theme Specification][] including a `theme.styles` object for styling MDX elements and other components.
By adhering to a standard Theme Specification, Theme UI is designed to be interoperable with as many other libraries as possible.

[theme specification]: /theme-spec

## Colors

Add a `theme.colors` object to provide colors for a theme.
In order to ensure color palettes are as interoperable as possible, the following color keys should be used for defining a base set of colors:

<ColorKeys />

Beyond these base colors, any additional values can be added to a theme to augment the base color palette.

### Color modes

Multiple color modes, i.e. _dark mode_, can be handled with a nested `modes` object that matches the shape of the default colors.

```tsx
// example colors with dark mode
colors: {
  text: '#000',
  background: '#fff',
  primary: '#07c',
  modes: {
    dark: {
      text: '#fff',
      background: '#000',
      primary: '#0cf',
    }
  }
}
```

Learn more in the [color mode docs](/color-modes).

## Typography

Core typographic values can be stored in the following theme keys:

- `fonts` (font families)
- `fontSizes`
- `fontWeights`
- `lineHeights`
- `letterSpacings`

<Note>

Values defined as numbers are converted to pixel units where appropriate.
For other units, use string values, e.g. `'1em'`.

</Note>

```js
// example theme object
{
  colors,
  fonts: {
    body: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", sans-serif',
    heading: 'Georgia, serif',
    monospace: 'Menlo, monospace',
  },
  fontSizes: [
    12, 14, 16, 20, 24, 32, 48, 64
  ],
  fontWeights: {
    body: 400,
    heading: 700,
    bold: 700,
  },
  lineHeights: {
    body: 1.5,
    heading: 1.125,
  },
  letterSpacings: {
    body: 'normal',
    caps: '0.2em',
  },
}
```

## Value scales

The following theme keys are used to define scales for values that can be used in other parts of a theme:

- `space` (margin, padding, gap, etc)
- `sizes` (width, height, etc)
- `borders` (border)
- `borderWidths` (border-width)
- `borderStyles` (border-style)
- `radii` (border-radius)
- `shadows` (box-shadow)
- `zIndices` (z-index)

For example, after setting `space` like this in your theme:

```js
space: [0, 4, 8, 16, 32, 64, 128, 256, 512],
```

You can reference the array values in your theme styles, by index:

```js
<Box
  sx={{
    padding: 2 // Equals 8px
  }}
/>
```

The values can also be named using an object, like this:

```js
sizes: {
  wide: 2048,
  container: 1024,
  narrow: 512,
},
```

Then used by name, such as `sx={{ maxWidth: 'narrow' /* 512px */ }}`.

## Styles

Styles for elements rendered in MDX can be added to the `theme.styles` object.
This is the primary API for applying typographic styles in Markdown content.
Styles within this object have access to other values in the theme object, such as colors, fonts, and space.

```js
// example theme styles
{
  colors: {
    text: '#000',
    background: '#fff',
    primary: '#07c',
  },
  fonts: {
    body: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", sans-serif',
    heading: 'Georgia, serif',
  },
  fontWeights: {
    body: 400,
    heading: 700,
  },
  styles: {
    h1: {
      fontSize: 32,
      fontFamily: 'heading',
      fontWeight: 'heading',
      color: 'primary',
      mt: 4,
      mb: 2,
    },
  }
}
```

<Note>

To use these styles arbitrarily, such as for markup from a CMS, see the [BaseStyles component](/api#basestyles).

</Note>

## Root styles

To add base, top-level styles to the `<html>` element, use `theme.styles.root`.

```js
// example with root styles
{
  fonts: {
    body: 'system-ui, sans-serif',
    heading: 'Georgia, serif',
  },
  fontWeights: {
    body: 400,
    heading: 700,
  },
  styles: {
    root: {
      // uses the theme values provided above
      fontFamily: 'body',
      fontWeight: 'body',
    },
  },
}
```

<Note>

To disable applying styles to the `<html>` element, add the `config: { useRootStyles: false }` flag to your theme.

</Note>

## Breakpoints

To configure the default breakpoints used in responsive array values, add a `breakpoints` array to your theme.
Each breakpoint should be a string with a CSS length unit included or a string including a CSS media query.
String values with a CSS length unit will be used to generate a mobile-first (i.e. `min-width`) media query. 
The breakpoints can then be used to apply [responsive styles](/sx-prop/#responsive-values).

```js
// example custom breakpoints
{
  breakpoints: [
    '40em', '@media (min-width: 56em) and (orientation: landscape)', '64em',
  ],
}
```

## Configuration flags

The theme object can also include configuration options for Theme UI, which are nested in the `config` object.
The following keys can be used to enable and disable certain features.

| Flag                       | Default             | Description                                                                                                                                 |
| -------------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `useCustomProperties`      | `true`              | Enables CSS custom properties to help mitigate a flash of unstyled content during rehydration                                               |
| `useRootStyles`            | `true`              | Adds styles defined in `theme.styles.root` to the `<html>` element along with `color` and `background-color`                                |
| `initialColorModeName`     | `'default'`         | The key used for the top-level color palette in `theme.colors`                                                                              |
| `useColorSchemeMediaQuery` | `true`             | Initializes the color mode based on the `prefers-color-scheme` media query                                                                  |
| `useBorderBox`             | `true`              | Adds a global `box-sizing: border-box` style                                                                                                |
| `useLocalStorage`          | `true`              | Persists the color mode in `localStorage`                                                                                                   |

## Default theme

If your custom theme doesn’t override these properties, Theme UI will use these default values.

```js
{
  breakpoints: [40, 52, 64].map((n) => n + 'em'),
  space: [0, 4, 8, 16, 32, 64, 128, 256, 512],
  fontSizes: [12, 14, 16, 20, 24, 32, 48, 64, 72],
}
```

## Example theme

The following example is from the [Base Preset][example].

```js
// example base theme from @theme-ui/presets
export const theme = {
  breakpoints: ['40em', '52em', '64em'],
  space: [0, 4, 8, 16, 32, 64, 128, 256, 512],
  fonts: {
    body:
      'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", sans-serif',
    heading: 'inherit',
    monospace: 'Menlo, monospace',
  },
  fontSizes: [12, 14, 16, 20, 24, 32, 48, 64, 96],
  fontWeights: {
    body: 400,
    heading: 700,
    bold: 700,
  },
  lineHeights: {
    body: 1.5,
    heading: 1.125,
  },
  colors: {
    text: '#000',
    background: '#fff',
    primary: '#07c',
    secondary: '#30c',
    muted: '#f6f6f6',
  },
  text: {
    heading: {
      fontFamily: 'heading',
      lineHeight: 'heading',
      fontWeight: 'heading',
    },
  },
  styles: {
    root: {
      fontFamily: 'body',
      lineHeight: 'body',
      fontWeight: 'body',
    },
    h1: {
      variant: 'text.heading',
      fontSize: 5,
    },
    h2: {
      variant: 'text.heading',
      fontSize: 4,
    },
    h3: {
      variant: 'text.heading',
      fontSize: 3,
    },
    h4: {
      variant: 'text.heading',
      fontSize: 2,
    },
    h5: {
      variant: 'text.heading',
      fontSize: 1,
    },
    h6: {
      variant: 'text.heading',
      fontSize: 0,
    },
    pre: {
      fontFamily: 'monospace',
      overflowX: 'auto',
      code: {
        color: 'inherit',
      },
    },
    code: {
      fontFamily: 'monospace',
      fontSize: 'inherit',
    },
    table: {
      width: '100%',
      borderCollapse: 'separate',
      borderSpacing: 0,
    },
    th: {
      textAlign: 'left',
      borderBottomStyle: 'solid',
    },
    td: {
      textAlign: 'left',
      borderBottomStyle: 'solid',
    },
  },
}
```

For alternative pre-made themes, check out the [presets package](/packages/presets),
and to see open source custom themes, check out [this collection](/resources#custom-themes).
For more information on the Theme UI `theme` object, see the [Theme Specification docs](/theme-spec).

[example]: https://github.com/system-ui/theme-ui/tree/develop/packages/preset-base/src/index.ts
[emotion]: https://emotion.sh
